<template>
  <AsyncModal v-if="asyncDomRender" class="async-model-container" v-bind="{ ...$attrs, ...props, title: undefined }" @cancel="modelCancel" :footer="null">
    <template #title>
      <div ref="modalTitleRef" :style="{ cursor: draggable ? 'move' : '' }">{{ title }}</div>
    </template>
    <div class="async-model-content">
      <slot></slot>
    </div>

    <!-- 底部按钮区域 -->
    <div class="async-model-footer">
      <template v-if="$slots.footer">
        <slot name="footer"></slot>
      </template>
      <template v-else>
        <a-space class="async-model-footer-button">
          <a-button @click="modelCancel">{{ cancelButtonText }}</a-button>
          <a-button v-if="showConfirmButton" type="primary" :loading="confirmLoading || thisConfirmLoading" @click="vxeModalConfirm">{{ confirmButtonText }}</a-button>
        </a-space>
      </template>
    </div>

    <template #modalRender="{ originVNode }">
      <div :style="transformStyle">
        <component :is="originVNode" />
      </div>
    </template>
  </AsyncModal>
</template>

<script lang="ts" setup>
defineOptions({
  name: 'AsyncModal'
})
import { defineAsyncComponent, ref, watch } from 'vue'
import useModelDraggable from './useModelDraggable'
const AsyncModal = defineAsyncComponent(() => import('./importModal'))

/**
 * @apiPath   https://www.antdv.com/components/modal-cn#api
 * @tips      除以下属性也可传递antd-vue-model文档其他属性
 * @addParam  cancelButtonText    自定义--取消按钮-文字
 * @addParam  showConfirmButton   自定义--是否显示-确认按钮
 * @addParam  confirmLoading      自定义--确认按钮-loading
 * @addParam  confirmButtonText   自定义--确认按钮-文字
 * @addEvent  cancel              自定义--取消按钮-事件
 * @addEvent  ok                  自定义--确认按钮-事件
 */
const props: { [attr: string]: any } = defineProps({
  // 显示弹窗
  open: {
    type: Boolean,
    default: false
  },
  // 是否启用窗口拖动
  draggable: {
    type: Boolean,
    default: false
  },
  // 弹窗标题
  title: {
    type: String,
    default: '窗口'
  },
  // 取消按钮的文本内容
  cancelButtonText: {
    type: String,
    default: '取消'
  },
  // 是否显示确定按钮
  showConfirmButton: {
    type: Boolean,
    default: true
  },
  // 确定按钮loading状态
  confirmLoading: Boolean,
  // 确定按钮的文本内容
  confirmButtonText: {
    type: String,
    default: '确定'
  }
})

// 拖拽
const modalTitleRef = ref<HTMLElement>()
let transformStyle: any
if (props.draggable) {
  watch(
    () => props.open,
    newVal => {
      if (newVal) {
        Promise.resolve().then(() => {
          // 记录上次拖拽的位置，优先取上次的transform数据
          transformStyle = transformStyle || useModelDraggable(modalTitleRef)?.transformStyle || {}
        })
      }
    }
  )
}

// 调用父组件方法
const emits = defineEmits(['update:open', 'cancel', 'update:modelValue', 'ok'])

// 取消事件
const modelCancel = () => {
  emits('cancel')
  emits('update:open', false)
}

// 确定事件
const vxeModalConfirm = () => {
  emits('ok', vxeModalConfirmCallBack)
}

// 确定事件callback--使按钮loading
const thisConfirmLoading = ref(false)
const vxeModalConfirmCallBack = (confirmPromise: Promise<any>) => {
  if (confirmPromise instanceof Promise) {
    thisConfirmLoading.value = true
    confirmPromise
      .then(() => {
        thisConfirmLoading.value = false
      })
      .catch(() => {})
  } else {
    console.warn('VxeModel的onConfirm方法回调函数形参只能为Promise，按钮loading效果才能生效')
  }
}

// model dom懒加载
const asyncDomRender = ref(false)
const unwatch = watch(
  () => props.open,
  newVal => {
    if (newVal) {
      asyncDomRender.value = true
      Promise.resolve().then(() => {
        unwatch && unwatch()
      })
    }
  },
  { immediate: true }
)
</script>

<style lang="less" scoped>
.async-model-container {
  display: flex;
  flex-direction: column;
  .ant-modal-header {
  }
  .async-model-content {
    margin-top: 20px;
    max-height: 60vh;
    flex: 1;
    overflow: auto;
  }
  .async-model-footer {
    margin-top: 12px;
    flex: none;
    display: flex;
    .async-model-footer-button {
      flex: 1;
      width: 100%;
      display: flex;
      justify-content: center;
    }
  }
}
</style>
./useModelDraggable
